﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Linq;

namespace ReporterEngine
{
    public abstract class ReportEngine<model, current_node, current_design> where model : Model<XElement>
    {
        public model Model { get; set; }
        
        public abstract void Report(ReportArgs args);

        public static ReportArgs CreateArgs()
        {
            return new ReportArgs();
        }

        public class ReportArgs
        {
            public current_node CurrentData { get; set; }
            public current_design CurrentDesign { get; set; }

            

            public Dictionary<string, current_node> NamedData = new Dictionary<string, current_node>();
        }


        protected static bool ContainsCommand(string text)
        {
            if (CommandExp.IsMatch(text))
            {
                return true;
            }

            return false;
        }

        protected static TemplateCommand GetFirstCommand(string text)
        {
            if (CommandExp.IsMatch(text))
            {
                var matchResult = CommandExp.Match(text);

                var commandIndex = matchResult.Index;

                var command = matchResult.Groups["command"].Value.Trim();
                var sectionname = matchResult.Groups["sectionname"].Value;
                var query = matchResult.Groups["query"].Value;


                if (!string.IsNullOrEmpty(command))
                    command = command.ToLower();

                var resCommand = new TemplateCommand
                                     {
                                         CommandName = command,
                                         SectionName = sectionname,
                                         Query = query,
                                         Index = commandIndex
                                     };

                return resCommand;
            }

            return TemplateCommand.Undefined;
        }

        public QueryResult ValidateSections(string content)
        {
            var result = new QueryResult();

            var matchSection = StartSectionExp.Matches(content);
            var matchEndSection = EndSectionExp.Matches(content);

            var startCount = matchSection.Count;
            var endCount = matchEndSection.Count;

            if (startCount > endCount)
            {
                result.Errors.Add(string.Format("Missing {0} EndSection(s)",startCount - endCount));
            }

            if (startCount < endCount)
            {
                result.Errors.Add(string.Format("Missing {0} StartSection(s)", endCount - startCount));
            }

            return result;
        }

        #region regex
        /// <summary>
        /// http://gskinner.com/RegExr/
        /// zaciatok {section@name > test > test2 < subject} pokracovanie
        /// zaciatok {section @ name > test > test2 < subject} pokracovanie
        /// zaciatok {section > test > test2 < subject} pokracovanie
        /// zaciatok {section > test > .orderby(id, 'name' desc, "description") < subject} pokracovanie
        /// zaciatok {section > (Use Cases, Events) > [name == "test"] > .orderby(id, 'name' desc, "description") < subject} pokracovanie
        /// </summary>
        //{section>> ('Activity Usages') >> [ << end, start >> count() == “4”]}
        public static readonly Regex CommandExp = new Regex("\\{(?<command>[\\w\\s]*)(?<sectionname>[\\:\\w\\s]*)(?<query>[\\>\\<]*[" + operators + "\\[\\]\\\"\\'\\’\\‚\\‘\\”\\“\\„\\.\\<\\>\\+\\w\\s\\#\\$\\(\\)\\,\\@]*)\\}");
        public static readonly Regex PureCommandExp = new Regex("(?<command>[\\w\\s]*)(?<sectionname>[\\:\\w\\s]*)(?<query>[\\>\\<]*[" + operators + "\\[\\]\\\"\\'\\’\\‚\\‘\\”\\“\\„\\.\\<\\>\\+\\w\\s\\#\\$\\(\\)\\,\\@]*)");

        //public static readonly Regex ParamExp = new Regex("\\{(?<command>[\\w\\s]*)(?<sectionname>[\\:\\w\\s]*)(?<query>[\\>\\<]*[" + operators + "\\[\\]\\\"\\'\\’\\‚\\‘\\”\\“\\„\\.\\<\\>\\+\\w\\s\\#\\$\\(\\)\\,\\@]*)\\}");
        public static readonly Regex ParamExp = new Regex("\\@(?<param>\\w+)");

        /// <summary>
        /// ==, !=, ||, &&, *= , ^=
        /// </summary>
        public const string operators = "\\=,\\~,\\!,\\^,\\*\\&\\|";

        public static readonly Regex StartSectionExp = new Regex("\\{[\\s]*s[\\s]*e[\\s]*c[\\s]*t[\\s]*i[\\s]*o[\\s]*n[\\w\\s]*[\\:\\>\\<]*");
        public static readonly Regex EndSectionExp = new Regex("\\{[\\s]*e[\\s]*n[\\s]*d[\\s]*s[\\s]*e[\\s]*c[\\s]*t[\\s]*i[\\s]*o[\\s]*n[\\s]*\\}");
        #endregion
    }
}
